package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.IdNamePropertyPojo;
import com.xbongbong.paas.pojo.dto.FixCcUserDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.service.WorkReportSetService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.DynamicManagerLevelEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.WorkReportApprovePeopleEntity;
import com.xbongbong.saas.domain.entity.WorkReportSetEntity;
import com.xbongbong.saas.domain.entity.ext.WorkReportEntityExt;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.WorkReportApprovePeopleModel;
import com.xbongbong.saas.model.WorkReportModel;
import com.xbongbong.saas.model.WorkReportSetModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 曹远远
 * @ProjectName xbb-web-script
 * @Description: 工作报告接口
 * @date 2020-06-09
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/workReport")
public class WorkReportScriptController {

    private static final Logger LOG = LoggerFactory.getLogger(WorkReportScriptController.class);

    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private ProductModel productModel;
    @Resource
    private WorkReportSetModel workReportSetModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private UserModel userModel;
    @Resource
    private WorkReportModel workReportModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private WorkReportApprovePeopleModel workReportApprovePeopleModel;
    @Resource
    private WorkReportSetService workReportSetService;


    /**
     * 第一步更新CcUser字段
     *
     * @param fixCcUserDTO
     * @param br
     * @return
     */
    @RequestMapping(value = "/fixCcUserField", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixCcUserField(@RequestBody @Valid FixCcUserDTO fixCcUserDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixCcUserDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixCcUserDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = workReportSetModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        List<Long> failList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        for (String corpid : corpidList) {
            param.put(ParameterConstant.CORPID, corpid);
            // Integer totalCount = workReportSetModel.getEntitysCount(param);
            // LOG.warn("corpid:" + corpid + "数据库中共有工作报告设置" + totalCount + "条数据");

            List<WorkReportSetEntity> workReportSetEntityList = workReportSetModel.findEntitys(param);
            if (workReportSetEntityList.isEmpty()) {
                continue;
            }
            for (WorkReportSetEntity workReportSetEntity : workReportSetEntityList) {
                boolean update = false;
                try {
                    JSONArray ccUserJSONArray = workReportSetEntity.getCcUser();
                    if (Objects.isNull(ccUserJSONArray) || ccUserJSONArray.size() == 0) {
                        continue;
                    }
                    for (int i = 0; i < ccUserJSONArray.size(); i++) {
                        JSONObject ccUserObj = ccUserJSONArray.getJSONObject(i);
                        JSONArray users = ccUserObj.getJSONArray(BasicConstant.USERS);
                        JSONArray approvedPeoples = ccUserObj.getJSONArray(BasicConstant.APPROVED_PEOPLE);
                        JSONArray effectiveDeps = ccUserObj.getJSONArray(BasicConstant.EFFECTIVE_DEPS);
                        JSONArray newUsers = new JSONArray();
                        JSONArray newApprovedPeoples = new JSONArray();
                        JSONArray newEffectiveDeps = new JSONArray();
                        if (Objects.nonNull(users) && users.size() != 0) {
                            for (int j = 0; j < users.size(); j++) {
                                JSONObject user = users.getJSONObject(j);
                                String userId = user.getString(BasicConstant.USERID);
                                String name = user.getString(BasicConstant.NAME);
                                JSONObject newUser = new JSONObject();
                                newUser.put(BasicConstant.ID, userId);
                                newUser.put(BasicConstant.NAME, name);
                                newUser.put(BasicConstant.PROPERTY, BasicConstant.USER);
                                newUsers.add(newUser);
                            }
                        }

                        // 所有层级主管
                        for (DynamicManagerLevelEnum cacheCode : DynamicManagerLevelEnum.values()) {
                            if (Objects.equals(DynamicManagerLevelEnum.ZERO_LEVEL, cacheCode)) {
                                continue;
                            }
                            JSONObject approvedPeople = new JSONObject();
                            approvedPeople.put(BasicConstant.ID, cacheCode.getLevel());
                            approvedPeople.put(BasicConstant.NAME, cacheCode.getName());
                            approvedPeople.put(BasicConstant.PROPERTY, BasicConstant.DYNAMICMANAGER);
                            newApprovedPeoples.add(approvedPeople);
                        }

                        // 发送人部门名称
                        Map<Long, String> ccDepMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        List<IdNamePropertyPojo> idNamePojoList = new ArrayList<>();
                        if (Objects.nonNull(effectiveDeps) && effectiveDeps.size() != 0) {
                            List<Long> effectiveDepsLong = effectiveDeps.toJavaList(java.lang.Long.class);
                            List<DepartmentEntity> departmentList = departmentModel.getDepartmentNamesByIds(corpid, effectiveDepsLong, false);
                            for (DepartmentEntity departmentEntity : departmentList) {
                                ccDepMap.put(departmentEntity.getId(), departmentEntity.getName());
                            }
                            if (!effectiveDepsLong.isEmpty()) {
                                for (Long depId : effectiveDepsLong) {
                                    if (ccDepMap.containsKey(depId)) {
                                        IdNamePropertyPojo idNamePropertyPojo = new IdNamePropertyPojo();
                                        idNamePropertyPojo.setId(Objects.toString(depId));
                                        idNamePropertyPojo.setName(ccDepMap.get(depId));
                                        idNamePropertyPojo.setProperty(BasicConstant.DEPT);
                                        idNamePojoList.add(idNamePropertyPojo);
                                    }
                                }
                            }
                        }
                        ccUserObj.put(BasicConstant.USERS, newUsers);
                        ccUserObj.put(BasicConstant.APPROVED_PEOPLE, newApprovedPeoples);
                        ccUserObj.put(BasicConstant.EFFECTIVE_DEPS, idNamePojoList);
                    }
                    workReportSetModel.update(workReportSetEntity);
                    update = true;
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (!update) {
                    failList.add(workReportSetEntity.getId());
                }

            }

            ++corpidCount;
            LOG.warn("CcUser:" + corpidCount + "/" + corpidList.size());
        }

        //if (failList.isEmpty()) {
        LOG.warn( "更新成功over");
        return null;
        //} else {
         //   throw new XbbException(ErrorCodeEnum.API_SUCCESS, "部分更新成功，id " + failList + "更新失败");
        //}
    }

    @RequestMapping(value = "/fixCcUserIds", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixCcUserIds(@RequestBody @Valid FixCcUserDTO fixCcUserDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixCcUserDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixCcUserDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = workReportSetModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        List<Long> failList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        for (String corpid : corpidList) {
            param.put(ParameterConstant.CORPID, corpid);
            // Integer totalCount = workReportSetModel.getEntitysCount(param);
            // LOG.warn("corpid:" + corpid + "数据库中共有工作报告设置" + totalCount + "条数据");
            List<WorkReportSetEntity> workReportSetEntityList = workReportSetModel.findEntitys(param);
            if (workReportSetEntityList.isEmpty()) {
                continue;
            }
            Map<String,String> nameIdMapping = userModel.getUserNameMapping(corpid);
            for (WorkReportSetEntity workReportSetEntity : workReportSetEntityList) {
                JSONArray ccUserJSONArray = workReportSetEntity.getCcUser();
                if (Objects.isNull(ccUserJSONArray) || ccUserJSONArray.size() == 0) {
                    continue;
                }
                for (int i = 0; i < ccUserJSONArray.size(); i++) {
                    JSONObject ccUserObj = ccUserJSONArray.getJSONObject(i);
                    JSONArray newUsers = new JSONArray();
                    JSONArray users = ccUserObj.getJSONArray(BasicConstant.USERS);
                   // JSONArray effectiveDeps = ccUserObj.getJSONArray(BasicConstant.EFFECTIVE_DEPS);
                    if (Objects.nonNull(users) && users.size() != 0) {
                        for (int j = 0; j < users.size(); j++) {
                            JSONObject user = users.getJSONObject(j);
                            String name = user.getString(BasicConstant.NAME);
                            String userId = user.getString(BasicConstant.ID);
                            if (!user.containsKey(BasicConstant.ID)){
                                userId = nameIdMapping.get(name);
                            }
                            JSONObject newUser = new JSONObject();
                            newUser.put(BasicConstant.ID, userId);
                            newUser.put(BasicConstant.NAME, name);
                            newUser.put(BasicConstant.PROPERTY, BasicConstant.USER);
                            newUsers.add(newUser);
                        }
                    }

                    ccUserObj.put(BasicConstant.USERS, newUsers);
                }
                workReportSetModel.update(workReportSetEntity);
            }
            ++corpidCount;
            LOG.warn("CcUser:" + corpidCount + "/" + corpidList.size());
        }

        //if (failList.isEmpty()) {
        LOG.warn( "更新成功over");
        return null;
    }

    @RequestMapping(value = "/fixApprovedPeople", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixApprovedPeople(@RequestBody @Valid FixCcUserDTO fixCcUserDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixCcUserDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long startTime = DateTimeUtil.getInt();
        LOG.info("工作报告开始更新数据，更新记录时间："+ startTime);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> corpidList = fixCcUserDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("columns","distinct(corpid)");
            List<WorkReportEntityExt> workReportEntityExtList = workReportModel.findEntitys(param);
            for (int i = 0; i < workReportEntityExtList.size(); i++) {
                WorkReportEntityExt workReportEntityExt = workReportEntityExtList.get(i);
                corpidList.add(workReportEntityExt.getCorpid());
            }
            if (Objects.nonNull(fixCcUserDTO.getExcludeCorpidList())){
                corpidList.removeAll(fixCcUserDTO.getExcludeCorpidList());
            }
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");

        Map<String, JSONObject> workReportSetMap =  new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (int i = 0; i < corpidList.size(); i++) {
            LOG.info("正在找第 " + i + "家公司的设置，总共" + corpidList.size() + "家公司");
            String corpid = corpidList.get(i);
            // 获取公司的所有部门
            List<DepartmentEntity> allDepList = departmentModel.findAllDepartment(corpid, true);
            Map<Long, DepartmentEntity> allDepMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (DepartmentEntity department : allDepList) {
                allDepMap.put(department.getId(), department);
            }
            // 顶级部门的主管
            DepartmentEntity topDepartment = allDepMap.get(1L);
            List<String> topManagerList = new ArrayList<>();
            if (Objects.nonNull(topDepartment)){
                topManagerList = userDepartmentModel.getDepManagerList(topDepartment);
            }
            // 获取公司所有的员工
            param.clear();
            param.put("corpid",corpid);
            param.put("columns","distinct(user_id),department");
            List<UserEntity> allUserList = userModel.findEntitys(param);
            for (int j = 0; j < allUserList.size(); j++) {
                UserEntity user = allUserList.get(j);
                String department = user.getDepartment();
                String userId = user.getUserId();
                Set<String> deptIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Set<String> roleIdIn =  new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Set<String> userIdIn =  new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<String> levelList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                // 每个人的日报 周报 月报批阅人设置
                List<Integer> typeList = Arrays.asList(1,2,3);
                for (int k = 0; k < typeList.size(); k++) {
                    Integer type = typeList.get(k);
                    UserEntity userEntity = new UserEntity();
                    userEntity.setCorpid(corpid);
                    userEntity.setDepartment(department);
                    userEntity.setUserId(userId);
                    // 兼容老板不在任何部门
                    List<IdNamePropertyPojo>  approvedPeopleList = new ArrayList<>();
                    if (Objects.isNull(department) || StringUtil.isEmpty(department)){
                        IdNamePropertyPojo idNamePropertyPojo = new IdNamePropertyPojo();
                        idNamePropertyPojo.setId(userId);
                        idNamePropertyPojo.setName("");
                        idNamePropertyPojo.setProperty("user");
                        approvedPeopleList.add(idNamePropertyPojo);
                    } else {
                        try{
                            approvedPeopleList = workReportSetService.getApprovedPeopleList(userEntity,type);
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    for (int l = 0; l < approvedPeopleList.size(); l++) {
                        IdNamePropertyPojo idNamePropertyPojo = approvedPeopleList.get(l);
                        String property = idNamePropertyPojo.getProperty();
                        String pojoId = idNamePropertyPojo.getId();
                        if (Objects.equals(property,BasicConstant.DEPT)){
                            deptIdIn.add(pojoId);
                        } else if (Objects.equals(property,BasicConstant.ROLE)){
                            roleIdIn.add(pojoId);
                        } else if (Objects.equals(property,BasicConstant.DYNAMICMANAGER)){
                            levelList.add(pojoId);
                        } else if (Objects.equals(property,BasicConstant.USER)){
                            userIdIn.add(pojoId);
                        }
                    }
                    // 所有要查询的部门
                    List<Long> depIdList = new ArrayList<>();
                    List<Long> departmentIds = JSONArray.parseArray(department,java.lang.Long.class);
                    if (CollectionsUtil.isNotEmpty(departmentIds)){
                        List<DepartmentEntity> departmentEntityList = departmentModel.findEntitysByDepartmentIds(departmentIds,corpid);
                        for (int m = 0; m < departmentEntityList.size(); m++) {
                            DepartmentEntity departmentEntity = departmentEntityList.get(m);
                            List<Long> routDepIds = StringUtil.toLongList(departmentEntity.getDepIdRouter(), "|");
                            int size = routDepIds.size();
                            for (String level : levelList) {
                                int levelInt = Integer.parseInt(level);
//                                if (levelInt > 0){
//                                    levelInt ++;
//                                }
                                // 顶级主管
                                if(levelInt >= size || levelInt == -1) {
                                    userIdIn.addAll(topManagerList);
                                } else {
                                    // 级别的主管
                                    Long depId = routDepIds.get(size - levelInt);
                                    depIdList.add(depId);
                                }
                            }
                        }
                    }
                    param.clear();
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    param.put("isLeader", 1);
                    param.put("departmentIdIn", depIdList);
                    List<UserDepartmentEntity> userDeptList = userDepartmentModel.findEntitys(param);
                    for(UserDepartmentEntity userDepartmentEntity : userDeptList) {
                        userIdIn.add(userDepartmentEntity.getUserId());
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("userIdIn",userIdIn);
                    jsonObject.put("deptIdIn",deptIdIn);
                    jsonObject.put("roleIdIn",roleIdIn);
                    workReportSetMap.put(corpid + "_" + userId + "_" + type,jsonObject);
                }
            }
        }

        Long addTimeStart = fixCcUserDTO.getAddTimeStart();
        Long addTimeEnd = fixCcUserDTO.getAddTimeEnd();
        param.clear();
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("corpidIn", corpidList);
        param.put("addTimeStart",addTimeStart);
        param.put("addTimeEnd",addTimeEnd);
        param.put("orderByStr","add_time asc");
        Integer totalCount = workReportModel.getEntitysCount(param);
        LOG.info("工作报告共有" + totalCount + "条记录");
        int pageSize = 1000;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
        Set<Long> failList = new HashSet<>();
        for (int page = 0; page < totalPage; page++) {
            if (page == totalPage - 1) {
                param.put("pageNum", lastPageSize);
            } else {
                param.put("pageNum", pageSize);
            }
            param.put("start", page * pageSize);
            LOG.info("第" + (page + 1) + "页开始");
            List<WorkReportEntityExt> workReportExtList = workReportModel.findEntitys(param);
            if (workReportExtList.isEmpty()) {
                continue;
            }
            for (WorkReportEntityExt workReportEntityExt : workReportExtList) {
                JSONObject data = workReportEntityExt.getData();
                Long reportId = workReportEntityExt.getId();
                String type = data.getString(WorkReportFieldEnum.TYPE.getAttr());
                String corpid = workReportEntityExt.getCorpid();
                String userId = workReportEntityExt.getCreatorId();
                JSONObject workReportSetJSON = workReportSetMap.get(corpid + "_" + userId + "_" + type);
                if (Objects.nonNull(workReportSetJSON)){
                    Set<String> userIds = (Set<String>) workReportSetJSON.get("userIdIn");
                    Set<String> deptIds = (Set<String>) workReportSetJSON.get("deptIdIn");
                    Set<String> roleIds = (Set<String>) workReportSetJSON.get("roleIdIn");
                    List<WorkReportApprovePeopleEntity> list = new ArrayList<>();
                    for (String deptId : deptIds) {
                        WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
                        entity.setApprovedPeople(deptId);
                        entity.setRefType(2);
                        entity.setReportId(reportId);
                        entity.setCorpid(corpid);
                        list.add(entity);
                    }
                    for (String roleId : roleIds) {
                        WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
                        entity.setApprovedPeople(roleId);
                        entity.setRefType(3);
                        entity.setReportId(reportId);
                        entity.setCorpid(corpid);
                        list.add(entity);
                    }
                    for (String user : userIds) {
                        WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
                        entity.setApprovedPeople(user);
                        entity.setRefType(1);
                        entity.setReportId(reportId);
                        entity.setCorpid(corpid);
                        list.add(entity);
                    }
                    try{
                        if (CollectionsUtil.isNotEmpty(list)){
                            workReportApprovePeopleModel.insertBatch(list);
                        }
                    } catch (Exception e){
                        failList.add(reportId);
                        e.printStackTrace();
                    }
                }

            }
            LOG.info("工作报告记录数页数进度" + (page + 1) + "/" + totalPage);
        }
        LOG.info( "work report update over");
        long endTime = DateTimeUtil.getInt();
        LOG.info("工作报告结束更新数据，更新记录时间："+ endTime);
        LOG.info("--------------work report consume time："+ (endTime-startTime) + "s");
        if (CollectionsUtil.isNotEmpty(failList)){
            LOG.info("--------------there is fail , reportId is："+ failList.toString());
        }
        return null;
    }
}
